#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#include <iostream>
#include <list>
#include <map>
#include <mutex>
#include <queue>
#include <thread>

#include "flv-muxer.h"
#include "flv-writer.h"
#include "librtspclient.h"
#include "mongoose.h"

class FlvStreamServer {
 public:
  FlvStreamServer(int port,std::string rtspurl);
  ~FlvStreamServer();
  void run();
  void sendFrame(const void* flvtag, int len, int codec = 7);

 private:
  static void eventHandlerWrapper(struct mg_connection* nc, int ev,
                                  void* ev_data);
  void eventHandler(struct mg_connection* nc, int ev, void* ev_data);
  void sendQueuedData();
  bool SendDataFlv(struct mg_connection* nc, const char* pData, int len,
                   bool needheader = true);
  bool HttpSend(struct mg_connection* nc, const char* pData, int len);
  bool SendFlvHeaderTag(struct mg_connection* nc);

 private:
  flv_muxer_t* CreateFlvMuxer(void* pUsrData);
  static int OnFlvPack(void* flv, int type, const void* data, size_t bytes,
                       uint32_t timestamp);
  uint32_t gettimems();

  int RtspStart(const char* url);
  int RtspStop();
  static int RTSPSourceCall(EASY_FRAME_INFO_T frameinfo, void* userdata);
  static void* RtspProcess(void* args);

 private:
  struct mg_mgr mgr_;
  struct mg_connection* nc_;
  std::map<struct mg_connection*, void*> connection_map_;
  std::list<std::string> queue_;
  std::mutex queue_mutex_;
  std::string metadata_;
  std::string httpport_;

  RTSP_Handle* hRTSPHandle_;
  bool RtspRunnig_;
  std::string RtspUrl_;
  pthread_t rtsp_thd_;
};